﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TextDataExtractor.DEML.Filters;

namespace TextDataExtractor.DEML {

	public enum ElementType {
		Unknown, Pattern, ExtractAction, TextLocator, DataFilter
	}

	public class DemlFactory {
		private IDictionary<string, Type> elementClasses;

		private static DemlFactory instance = new DemlFactory();

		public static DemlFactory Instance { get { return instance; } }

		private DemlFactory() {
			elementClasses = new Dictionary<string, Type>();

			registerElement<Section>(ElementType.Pattern, "section");
			registerElement<DataPart>(ElementType.Pattern, "data-part");
			registerElement<XmlDataPart>(ElementType.Pattern, "xmldata-part");
			registerElement<CompositePattern>(ElementType.Pattern, "pattern");
			registerElement<InclusionPattern>(ElementType.Pattern, "include");
			registerElement<SelectivePattern>(ElementType.Pattern, "or");
			
			registerElement<NewObjectAction>(ElementType.ExtractAction, "new");
			registerElement<SetDataAction>(ElementType.ExtractAction, "set");
			registerElement<SetDataAction>(ElementType.ExtractAction, "append");
			registerElement<CompositeAction>(ElementType.ExtractAction, "actions");
			registerElement<ForEachAction>(ElementType.ExtractAction, "foreach");

			registerElement<FindTextLocator>(ElementType.TextLocator, "find");

			registerElement<RemoveHtmlTagFilter>(ElementType.DataFilter, "RemoveHtmlTag");
			registerElement<TrimFilter>(ElementType.DataFilter, "Trim");
			registerElement<TrimFilter>(ElementType.DataFilter, "TrimAll");
			registerElement<TrimFilter>(ElementType.DataFilter, "TrimLeft");
			registerElement<TrimFilter>(ElementType.DataFilter, "TrimRight");
			registerElement<TypeConvertFilter>(ElementType.DataFilter, "TypeConvert");
		}

		public void registerElement<T>(ElementType type, string name) where T : IDemlElement {
			elementClasses[type.ToString().ToLower() + ":" + name.ToLower()] = typeof(T);
		}

		public void registerElement(Type elementType, ElementType type, string name) {
			elementClasses[type.ToString().ToLower() + ":" + name.ToLower()] = elementType;
		}

		public object createElement(ElementType type, string name) {
			Type ctype = null;
			if (elementClasses.TryGetValue(type.ToString().ToLower() + ":" + name.ToLower(), out ctype))
				return Activator.CreateInstance(ctype);
			return null;
		}

		public ElementType getElementType(string name) {
			foreach (ElementType type in Enum.GetValues(typeof(ElementType)))
				if (isElementType(type, name)) return type;
			return ElementType.Unknown;
		}

		public bool isElementType(ElementType type, string name) {
			return elementClasses.ContainsKey(type.ToString().ToLower() + ":" + name.ToLower());
		}
	}
}
